/*
 * Frame.java  0.4.0 / Oct 26, 2010
 *
 * Copyright (c) 2010 - 2011, cute4j.com and contributors.
 *
 * This software is licensed under the LGPL version 2.1 license.
 * A copy of this license is included in the file LICENSE-LGPL.txt.
 */
package com.cute4j.swing;

import java.util.ArrayList;

import com.cute4j.swing.graphics.Dimension;
import com.cute4j.swing.graphics.Insets;
import com.cute4j.swing.layouts.LayoutManager;

/**
 * Frame Component.
 *
 * @cute4j.native
 *    generate="header"
 *
 * @author Slobodan Vrkacevic
 * @version 0.4.0
 */
public class Frame extends Window {

// Package-Private Fields. -----------------------------------------------------

  MenuBar menuBar;
  ArrayList toolBars;
  Container contentPane;
  StatusBar statusBar;

// Protected Constructors. -----------------------------------------------------

  /**
   * Constructs new Frame object.
   */
  public Frame() {
    this(null);
  }

  /**
   * Constructs new Frame object.
   *
   * @param title the frame title
   */
  public Frame(String title) {
    super(null, title);
    toolBars = new ArrayList();
    contentPane = new ContentPane();
    _setContentPane(_delegate, contentPane._delegate); // NOPMD
  }

// Public Methods. -------------------------------------------------------------

  /**
   * Returns menu bar.
   *
   * @return menu bar
   */
  public MenuBar getMenuBar() {
    return menuBar;
  }

  /**
   * Sets menu bar.
   *
   * @param menuBar the menu bar
   *
   * @return menu bar
   */
  public MenuBar setMenuBar(MenuBar menuBar) {
    final MenuBar oldMenuBar = this.menuBar;
    if (oldMenuBar != menuBar) { // NOPMD
      disposedCheck();
      if (menuBar == null) {
        if (oldMenuBar != null) {
          releaseChild(oldMenuBar);
        }
        _setMenuBar(_delegate, 0);
        this.menuBar = null;
      } else {
        if (menuBar.isDisposed()) {
          throw new IllegalArgumentException("Adding disposed menu bar");
        }
        if (menuBar.parent != null) {
          throw new IllegalArgumentException("Adding parented menu bar");
        }
        acquireChild(menuBar);
        _setMenuBar(_delegate, menuBar._delegate);
        this.menuBar = menuBar;
      }
    }
    return menuBar;
  }

  /**
   * Returns the number of toolbars.
   *
   * @return the number of toolbars
   */
  public int getToolBarCount() {
    return toolBars.size();
  }

  /**
   * Returns the toolbar at specified index.
   *
   * @param index the index of the toolbar
   *
   * @return the toolbar at specified index
   *
   * @throws IndexOutOfBoundsException if index is out of range
   *         <tt>((index &lt; 0) | (index &gt;= getToolBarCount()))</tt>.
   */
  public ToolBar getToolBar(int index) {
    return (ToolBar)toolBars.get(index);
  }

  /**
   * Adds toolbar.
   *
   * @param toolBar the tool bar
   *
   * @return toolbar
   */
  public ToolBar addToolBar(ToolBar toolBar) {
    if (toolBar == null) {
      throw new IllegalArgumentException("Null toolbar");
    }
    if (toolBar.isDisposed()) {
      throw new IllegalArgumentException("Adding disposed toolBar");
    }
    if (toolBar.parent != null) {
      throw new IllegalArgumentException("Adding parented toolBar");
    }
    disposedCheck();
    acquireChild(toolBar);
    _addToolBar(_delegate, toolBar._delegate);
    toolBars.add(toolBar);
    return toolBar;
  }

  /**
   * Removes the specified toolbar.
   *
   * @param toolBar the toolbar to be removed
   */
  public void removeToolBar(ToolBar toolBar) {
    if ((toolBar != null) && !toolBar.isDisposed() &&
        (toolBar.parent != null)) {
      disposedCheck();
      releaseChild(toolBar);
      _removeToolBar(_delegate, toolBar._delegate);
      toolBars.remove(toolBar);
    }
  }

  /**
   * Returns status bar.
   *
   * @return status bar
   */
  public StatusBar getStatusBar() {
    return statusBar;
  }

  /**
   * Sets status bar.
   *
   * @param statusBar the status bar
   *
   * @return status bar
   */
  public StatusBar setStatusBar(StatusBar statusBar) {
    final StatusBar oldStatusBar = this.statusBar;
    if (oldStatusBar != statusBar) { // NOPMD
      disposedCheck();
      if (statusBar == null) {
        if (oldStatusBar != null) {
          releaseChild(oldStatusBar);
        }
        _setStatusBar(_delegate, 0);
        this.statusBar = null;
      } else {
        if (statusBar.isDisposed()) {
          throw new IllegalArgumentException("Adding disposed status bar");
        }
        if (statusBar.parent != null) {
          throw new IllegalArgumentException("Adding parented status bar");
        }
        acquireChild(statusBar);
        _setStatusBar(_delegate, statusBar._delegate);
        this.statusBar = statusBar;
      }
    }
    return statusBar;
  }

// Overridden Methods. ---------------------------------------------------------

  /**
   * {@inheritDoc}
   */
  public Dimension getPreferredSize() {
    if (!preferredSizeSet && (!valid || (preferredSize == null))) {
      disposedCheck();
      preferredSize = _getPreferredSize(_delegate);
      if (insets != null) {
        preferredSize = preferredSize.enlarge(insets.getLeft() +
                                              insets.getRight(),
                                              insets.getTop() +
                                              insets.getBottom());
      }
    }
    return preferredSize;
  }

  /**
   * {@inheritDoc}
   */
  public Insets getInsets() {
    return contentPane.getInsets();
  }

  /**
   * {@inheritDoc}
   */
  public void setInsets(Insets insets) {
    contentPane.setInsets(insets);
  }

  /**
   * {@inheritDoc}
   */
  public void invalidate() {
    contentPane.invalidate();
  }

  /**
   * {@inheritDoc}
   */
  public void validate() {
    contentPane.validate();
  }

  /**
   * {@inheritDoc}
   */
  public void setComponentOrientation(ComponentOrientation orientation) {
    super.setComponentOrientation(orientation);
    if (menuBar != null) {
      menuBar.setComponentOrientation(orientation);
    }
    for (int i = toolBars.size(); --i >= 0;) {
      ((ToolBar)toolBars.get(i)).setComponentOrientation(orientation);
    }
    contentPane.setComponentOrientation(orientation);
    if (statusBar != null) {
      statusBar.setComponentOrientation(orientation);
    }
  }

  /**
   * {@inheritDoc}
   */
  public void updateLocalization() {
    super.updateLocalization();
    if (title != null) {
      _setTitle(_delegate, localizeString(title));
    }
    if (menuBar != null) {
      menuBar.updateLocalization();
    }
    for (int i = toolBars.size(); --i >= 0;) {
      ((ToolBar)toolBars.get(i)).updateLocalization();
    }
    contentPane.updateLocalization();
    if (statusBar != null) {
      statusBar.updateLocalization();
    }
  }

  /**
   * {@inheritDoc}
   */
  public void remove(Component component) {
    contentPane.remove(component);
  }

  /**
   * {@inheritDoc}
   */
  public Component remove(int index) {
    return contentPane.remove(index);
  }

  /**
   * {@inheritDoc}
   */
  public Component getComponent(int index) {
    return contentPane.getComponent(index);
  }

  /**
   * {@inheritDoc}
   */
  public int getComponentCount() {
    return contentPane.getComponentCount();
  }

  /**
   * {@inheritDoc}
   */
  public LayoutManager getLayout() {
    return contentPane.getLayout();
  }

  /**
   * {@inheritDoc}
   */
  public void setLayout(LayoutManager layoutManager) {
    contentPane.setLayout(layoutManager);
  }

  /**
   * {@inheritDoc}
   */
  public void doLayout() {
    contentPane.doLayout();
  }

  /**
   * {@inheritDoc}
   */
  protected Component addImpl(Component comp, Object constraints,
                                int index) {
    return contentPane.addImpl(comp, constraints, index);
  }

  void destroyComponent() {
    super.destroyComponent();
    // menu bar, content pane and status bar are automatically destroyed
    for (int i = toolBars.size(); --i >= 0;) {
      ((ToolBar)toolBars.get(i)).dispose();
    }
  }
// Package-Private Native Method. ----------------------------------------------

  native long _create();

  native void _setMenuBar(long delegate, long menuBarDelegate);

  native void _addToolBar(long delegate, long toolBarDelegate);

  native void _removeToolBar(long delegate, long toolBarDelegate);

  native void _setContentPane(long delegate, long contentPaneDelegate);

  native void _setStatusBar(long delegate, long statusBarDelegate);

}
